/*   Copyright (C) 2008  Jeroen v. Schagen & Youri Lima
 *
 *   This program is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Text;
using System.IO;

namespace Engine.Connection
{
    public class StringStream : Stream
    {
        // Either write or read. Never both, interveres with _Pos idea. Stream related
        private bool mode;

        private string data;
        private int position;

        # region Constructor

        public StringStream() : this("")
        {
            // Overloaded
        }

        public StringStream(string data) : this(data, false)
        {
            // Overloaded
        }
        
        public StringStream(string data, bool write)
        {
            this.data = data;
            this.mode = write;
        }

        # endregion


        # region Function

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (mode) return -1;
            if (offset < 0) return -1;
            if (buffer.Length < (offset + count)) count = buffer.Length - offset;
            if (count < 1) return -1;
            if (buffer == null) buffer = new byte[offset + count];

            String d = data.Substring(position, count); position += count;
            byte[] pbuffer = Encoding.Unicode.GetBytes(d);

            for (int i = 0; i < pbuffer.Length; i++)
            {
                buffer[offset + i] = pbuffer[i];
            }

            return buffer.Length;
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override void SetLength(long value)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            if (!mode) throw new IOException("stream is in ReadMode, not writable");
            if (buffer == null) throw new IOException("nothing to write");
            if (offset < 0) throw new IOException("offset is set wrongly");
            if (buffer.Length < (offset + count)) count = buffer.Length - offset;
            if (count < 1) throw new IOException("count is set wrongly");

            byte[] pbuffer = new byte[count];

            for (int i = 0; i < pbuffer.Length; i++)
            {
                pbuffer[i] = buffer[offset + i];
            }

            data.Insert(position, new String(Encoding.Unicode.GetChars(pbuffer)));
        }

        # endregion


        # region Accessor

        public override bool CanRead
        {
            get { return !mode; }
        }

        public override bool CanSeek
        {
            get { return true; }
        }

        public override bool CanWrite
        {
            get { return mode; }
        }

        public override void Flush()
        {
            return;
        }

        public override long Length
        {
            get { return data.Length; }
        }

        public override long Position
        {
            get { return position; }
            set { position = (int) value; }
        }

        # endregion

        public override string ToString()
        {
            return data;
        }
    }
}
